package com.sdy.resdir.web.controller.admin;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.approval.api.ApprovalAllApi;
import com.sdy.auth.api.model.UserInfo;
import com.sdy.auth.client.service.SsoService;
import com.sdy.common.model.BizException;
import com.sdy.common.model.Response;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.StringUtil;
import com.sdy.dcsb.api.DcsbApi;
import com.sdy.resdir.biz.model.*;
import com.sdy.resdir.biz.service.*;
import com.sdy.resdir.biz.util.DeCodeUtil;
import com.sdy.resdir.biz.vo.IpApplyListVo;
import com.sdy.usercenter.api.UserQueryApi;
import com.sdy.usercenter.api.dto.DeptDto;
import com.sdy.usercenter.api.dto.UserDTO;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.sdy.mvc.controller.BaseController;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static javax.swing.text.html.HTML.Tag.S;


/**
 * 管理员接口类
 *
 * @author hyh
 * @since 2019-10-24
 */
@Slf4j
@RestController
@SuppressWarnings("unchecked")
@RequestMapping("/admin")
@Api(tags = "管理员接口Api")
public class AdminController extends BaseController {
    @Autowired
    private RdResourceDirService rdResourceDirService;
    @Autowired
    private RdResDetailsApiService rdResDetailsApiService;
    @Autowired
    private RdResourceDirDataService rdResourceDirDataService;
    @Autowired
    private RdImplementationOrderService implementationOrderService;
    @Autowired
    private UserQueryApi userQueryApi;
    @Autowired
    private ApprovalAllApi approvalAllApi;
    @Autowired
    private SsoService ssoService;
    @Autowired
    private RdIpUpdateApplicationService ipUpdateApplicationService;
    @Autowired
    private RdResourceApplicationDetailService rdResourceApplicationDetailService;
    @Autowired
    private AdminService adminService;
    @Autowired
    private RdOrderAppService rdOrderAppService;
    @Autowired
    private RdSystemIpService rdSystemIpService;
    @Autowired
    private RdSelfBuiltSystemService rdSelfBuiltSystemService;
    @Autowired
    private RdIpImpleOrderService rdIpImpleOrderService;
    @Autowired
    private DcsbApi dcsbApi;
    @Value("${res.dept.code}")
    private String deptCode;

    // ---------------------------------------------------资源管理-------------------------------------------------------

    @ApiOperation(value = "资源管理-获取部门列表", response = DeptDto.class)
    @ApiImplicitParam(name = "deptId", value = "部门prentId")
    @GetMapping("/getDeptList")
    public Response getDeptList(Integer deptId, String keyWord) throws UnsupportedEncodingException {
        // 查所有部门列表
        if (StringUtil.isNotEmpty(keyWord) && StringUtil.isNotBlank(keyWord)) {
            String param = DeCodeUtil.decodeParam(keyWord);
            return Response.success(userQueryApi.listDept(param));
        } else {
            return Response.success(userQueryApi.listDept(deptId));
        }
    }

    @ApiOperation(value = "资源管理-资源下架")
    @PostMapping("/resDown")
    public Response resDown(@RequestBody @ApiParam("id") Map<String, Object> map) throws BizException {
        Integer id = (Integer) map.get("id");
        Assert.isNull(id, "id不可为空");
        RdResourceDir one = rdResourceDirService.getOne(Wrappers.<RdResourceDir>lambdaQuery().eq(RdResourceDir::getId, id));
        Assert.isTrue(one.getIsRelease() == 0, "该资源已下架,不可重复下架");
        boolean state = rdResourceDirService.updateById(new RdResourceDir().setId(id).setIsRelease(0));
        return state ? Response.success() : Response.error();
    }

    @ApiOperation(value = "资源管理-分页查询资源-数据局使用", response = RdResourceDir.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "state", value = "资源状态: 0-已发布 1-未发布"),
            @ApiImplicitParam(name = "type", value = "资源类型: (1.服务接口类 2.服务页面类 3.数据教换类)"),
            @ApiImplicitParam(name = "resName", value = "资源名称:模糊查询")
    }
    )
    @GetMapping("/resPageList")
    public Response resPageList(Page page, Integer state, Integer type, String resName) throws UnsupportedEncodingException {
        resName = DeCodeUtil.decodeParam(resName);
        IPage<RdResourceDir> rdResourceDirIPage = rdResourceDirService.resPageList(page, state, type, resName);
        return Response.success(rdResourceDirIPage);
    }

    @ApiOperation("资源管理-根据id删除资源")
    @PostMapping("/delByResId")
    public Response delByResId(@RequestBody @ApiParam(name = "id", value = "资源id") Map<String, Object> map) throws BizException {
        Integer id = (Integer) map.get("id");
        RdResourceDir one = rdResourceDirService.getOne(Wrappers.<RdResourceDir>lambdaQuery().eq(RdResourceDir::getId, id));
        Assert.isNull(one, "找不到该资源");
        boolean remove;
        if (one.getResType().equals(1)) {
            remove = rdResDetailsApiService.remove(Wrappers.<RdResDetailsApi>lambdaUpdate().eq(RdResDetailsApi::getResDirId, id));
        } else {
            remove = rdResourceDirDataService.remove(Wrappers.<RdResourceDirData>lambdaUpdate().eq(RdResourceDirData::getResDirId, id));
        }
        boolean dir = rdResourceDirService.removeById(id);
        Assert.isTrue(!remove || !dir, "系统异常，请重试!");
        return Response.success();
    }

    @ApiOperation(value = "资源管理-查看资源详情", response = RdResourceDir.class)
    @ApiImplicitParam(name = "id", value = "资源Id")
    @GetMapping("/getResInfo")
    public Response getResInfo(Integer id) throws BizException {
        RdResourceDir one = rdResourceDirService.getOne(Wrappers.<RdResourceDir>lambdaQuery().eq(RdResourceDir::getId, id));
        Assert.isNull(one, "找不到该资源");
        return Response.success(one);
    }

    @ApiOperation("资源管理-修改资源信息")
    @PostMapping("/updateResInfo")
    public Response updateResInfo(HttpServletRequest request, @RequestBody @ApiParam(name = "res", value = "资源信息") RdResourceDir res) throws Exception {
        Date date = new Date();
        Integer userId = ssoService.getUserId(request);
        return adminService.updateResInfo(res, date, userId);
    }

    // ---------------------------------------------------资源审批-------------------------------------------------------

    @ApiOperation(value = "实施工单-分页查询", response = RdImplementationOrder.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "资源类型: (1.服务接口类 2.服务页面类 3.数据教换类)"),
            @ApiImplicitParam(name = "resName", value = "资源名称:模糊查询")
    }
    )
    @GetMapping("/implOrderList")
    public Response implOrderPageList(Page page, Integer type, String resName, HttpServletRequest request) throws Exception {
        Integer userId = ssoService.getUserInfo(request).getUserId();
        UserDTO user = userQueryApi.getUser(userId);
        resName = URLDecoder.decode(resName, "UTF-8");
        IPage<RdImplementationOrder> data = implementationOrderService.page(page, Wrappers.<RdImplementationOrder>lambdaQuery()
                .eq(null != type, RdImplementationOrder::getResType, type)
                .eq(RdImplementationOrder::getDeptId, user.getOwnDeptId())
                .eq(RdImplementationOrder::getOrderType, 1)
                .like(StringUtil.isNotEmpty(resName) && StringUtil.isNotBlank(resName), RdImplementationOrder::getResName, resName)
                .orderByDesc(RdImplementationOrder::getId));
        if (!data.getRecords().isEmpty()) {
            List<Integer> resIds = data.getRecords().stream().map(RdImplementationOrder::getResId).collect(Collectors.toList());
            List<String> applyNums = data.getRecords().stream().map(RdImplementationOrder::getApplyNum).collect(Collectors.toList());
            // 插入订单信息
            List<RdResourceApplicationDetail> listDetail = rdResourceApplicationDetailService.list(new LambdaQueryWrapper<RdResourceApplicationDetail>()
                    .in(RdResourceApplicationDetail::getApplyNumChild, applyNums)
                    .in(RdResourceApplicationDetail::getResId, resIds));
            for (int i = 0; i < data.getRecords().size(); i++) {
                if (data.getRecords().get(i).getApplyNum().equals(listDetail.get(i).getApplyNumChild())) {
                    data.getRecords().get(i).setRdResourceApplicationDetail(listDetail.get(i));
                }
            }
        }
        return Response.success(data);
    }

    @ApiOperation(value = "实施工单-修改实施状态 - 0 实施完成/ 1实施中/ 2取消实施")
    @PostMapping("/implDone")
    @Transactional(rollbackFor = Exception.class)
    public Response implDone(@RequestBody @ApiParam(name = "id，orderOperate", value = "工单id，操作类型（0 实施中 1 实施完成 2 取消实施）") Map<String, Object> map, HttpServletRequest request) throws BizException {
        Integer id = (Integer) map.get("id");
        Assert.isNull(id, "id不可为空");
        Date date = new Date();
        RdImplementationOrder rdImplementationOrder = implementationOrderService.getOne(Wrappers.<RdImplementationOrder>lambdaQuery().eq(RdImplementationOrder::getId, id));
        boolean updateState = true;
        Assert.isNull(map.get("orderOperate"), "无法操作类型，请联系管理员");
        if ((Integer) map.get("orderOperate") == 1) {
            updateState = implementationOrderService.updateById(new RdImplementationOrder().setId(id).setImplementationState(1));
            // 通过实施工单id拿到订单号
            String applyNum = rdImplementationOrder.getApplyNum();
            Integer resId = rdImplementationOrder.getResId();
            List<RdOrderApp> list = rdOrderAppService.list(Wrappers.<RdOrderApp>lambdaQuery().eq(RdOrderApp::getApplyNum, applyNum)
                    .isNull(RdOrderApp::getVersionNum));
            String ipIdStr = null;
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getIpId() != null) {
                    if (ipIdStr == null) {
                        ipIdStr = list.get(i).getIpId();
                    } else {
                        ipIdStr = ipIdStr + "," + list.get(i).getIpId();
                    }
                }
            }
            // 把所有的数据转换成list
            if (StringUtil.isNotBlank(ipIdStr)) {
                String[] split = ipIdStr.split(",");
                ArrayList<Integer> intIpIds = new ArrayList<>();
                for (int i = 0; i < split.length; i++) {
                    Integer integer = Integer.valueOf(split[i]);
                    intIpIds.add(integer);
                }
                // 拿到所有需要绑定资源id的ip数据
                List<RdSystemIp> rdSystemIps = rdSystemIpService.list(Wrappers.<RdSystemIp>lambdaQuery().in(RdSystemIp::getId, intIpIds));
                String strResId = String.valueOf(resId);
                for (int i = 0; i < rdSystemIps.size(); i++) {
                    if (rdSystemIps.get(i).getResIdList() == null) {
                        rdSystemIps.get(i).setResIdList(strResId);
                    } else {
                        String oldResIds = rdSystemIps.get(i).getResIdList();
                        String newResIds = oldResIds + "," + strResId;
                        rdSystemIps.get(i).setResIdList(newResIds);
                    }
                }
                // 实施完成时，绑定自建系统ip到资源
                Boolean aBoolean = rdSystemIpService.updateResIdsBetch(rdSystemIps);
                Assert.notTrue(aBoolean, "自建系统绑定资源时出错!");
            }
            Assert.isNull(rdImplementationOrder.getResId(), "无法获取资源信息.");
            RdResourceDir rdRes = rdResourceDirService.getOne(new LambdaQueryWrapper<RdResourceDir>().eq(RdResourceDir::getId, rdImplementationOrder.getResId()));
            if (rdRes != null && rdRes.getResType() == 1) {
            RdResDetailsApi rdResDetailsApi = rdResDetailsApiService.getOne(new LambdaQueryWrapper<RdResDetailsApi>()
                    .eq(RdResDetailsApi::getResDirId, rdImplementationOrder.getResId()));
            Assert.isNull(rdResDetailsApi, "无法获取资源信息!");
            Assert.isNull(rdResDetailsApi.getApiAddress(), "无法获取接口地址");
            List<String> addresses = new ArrayList<>();
            addresses.add(rdResDetailsApi.getApiAddress());
            List<RdOrderApp> rdOrderAppList = rdOrderAppService.list(new LambdaQueryWrapper<RdOrderApp>()
                    .eq(RdOrderApp::getApplyNum, rdImplementationOrder.getApplyNum())
                    .isNull(RdOrderApp::getVersionNum));
            Assert.isTrue(rdOrderAppList.isEmpty(), "无法获取自建系统信息.");
            List<String> systemCodes = rdOrderAppList.stream().map(RdOrderApp::getSysCode).collect(Collectors.toList());
            Assert.isTrue(systemCodes.isEmpty(), "无法获取自建系统信息!");
            List<RdSelfBuiltSystem> rdSelfBuiltSystemList = rdSelfBuiltSystemService.list(new LambdaQueryWrapper<RdSelfBuiltSystem>()
                    .in(RdSelfBuiltSystem::getSysCode, systemCodes));
            Assert.isTrue(rdSelfBuiltSystemList.isEmpty(), "无法获取自建系统信息!!");
            // ip开启资源权限
            for (RdOrderApp one : rdOrderAppList) {
                for (RdSelfBuiltSystem rd : rdSelfBuiltSystemList) {
                    if (one.getSysCode().equals(rd.getSysCode())) {
                        String name = rdIpImpleOrderService.getName(rd);
                        String[] ips = one.getIp().split(",");
                        Response response = dcsbApi.openInterfaceServiceAuthority(addresses, name, rd.getSysName(), ips);
                        Assert.isTrue(!response.getSuccess(), response.getMessage());
                    }
                }
            }
        }
        } else if ((Integer) map.get("orderOperate") == 2) {
            // 取消实施
            Integer userId = ssoService.getUserId(request);
            Assert.isNull(userId, "用户未登录");
            String cancelReason = (String) map.get("cancelReason");
            Assert.isNull(cancelReason, "取消实施请输入取消理由");
            Boolean withdraw = approvalAllApi.withdraw(rdImplementationOrder.getApplyNum(), userId, date, 0);
            Assert.notTrue(withdraw, "取消实施操作失败，申请单撤回失败");
            // 取消理由加入数据库
            boolean updateCancelReason = implementationOrderService.update(new LambdaUpdateWrapper<RdImplementationOrder>()
                    .eq(RdImplementationOrder::getId, id)
                    .set(RdImplementationOrder::getCancelReason, cancelReason));
            Assert.notTrue(updateCancelReason, "添加取消实施理由失败，请联系管理员");
            // 更新实施工单的状态
            boolean updateOrder = implementationOrderService.update(new LambdaUpdateWrapper<RdImplementationOrder>()
                    .eq(rdImplementationOrder.getId() != null, RdImplementationOrder::getId, rdImplementationOrder.getId())
                    .set(RdImplementationOrder::getImplementationState, map.get("orderOperate")));
            Assert.notTrue(updateOrder, "实施工单操作失败，请联系管理员");
            updateState = implementationOrderService.updateById(new RdImplementationOrder().setId(id).setImplementationState(2));
        }
        Assert.isTrue(!updateState, "修改订单实施状态失败，请联系管理员或稍后重试");
        return Response.success();
    }

    @ApiOperation(value = "回收资源")
    @PostMapping("/retrieveResource")
    public Response retrieveResource(@RequestBody @ApiParam(name = "resId", value = "资源id") Map<String, Object> map, HttpServletRequest request) throws BizException {
        Integer userId = ssoService.getUserId(request);
        Assert.isNull(userId, "用户未登录");
        List<Integer> ownDeptIdList = userQueryApi.getUser(userId).getOwnDeptIdList();
        if (!ownDeptIdList.contains(userQueryApi.getDeptByCode(deptCode).getId())) {
            return Response.error("登陆角色无该操作权限");
        }
        Assert.isNull(map.get("id"), "请输入请求数据id");
        RdImplementationOrder rdImplementationOrder = implementationOrderService.getOne(new LambdaQueryWrapper<RdImplementationOrder>()
                .eq(RdImplementationOrder::getId, map.get("id"))
                .eq(RdImplementationOrder::getOrderType, 1));
        Assert.isNull(rdImplementationOrder, "无法获取实施工单信息，请联系管理员");
        if (rdImplementationOrder.getImplementationState() != null && rdImplementationOrder.getImplementationState() == 4) {
            boolean updateApplyOrder = implementationOrderService.update(new LambdaUpdateWrapper<RdImplementationOrder>()
                    .eq(RdImplementationOrder::getId, map.get("id"))
                    .eq(RdImplementationOrder::getOrderType, 1)
                    .set(RdImplementationOrder::getImplementationState, 3));
            Assert.notTrue(updateApplyOrder, "申请单状态修改失败，请联系管理员");
        } else {
            return Response.error("当前资源不可回收");
        }
        return Response.success("资源回收成功！");
    }

    // --------------------------------------------------IP修改审核------------------------------------------------------

    @ApiOperation(value = "IP修改申请单-审核列表", response = IpApplyListVo.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "appName", value = "自建系统名称"),
            @ApiImplicitParam(name = "ip", value = "ip地址"),
            @ApiImplicitParam(name = "state", value = "资源名称:模糊查询")
    }
    )
    @GetMapping("/ipOrderManagerList")
    public Response ipOrderManagerList(Page page, String appName, String ip, Integer state, HttpServletRequest request) throws BizException, UnsupportedEncodingException {
        UserInfo userInfo = ssoService.getUserInfo(request);
        Assert.isNull(userInfo, "用户还未登录");
        appName = DeCodeUtil.decodeParam(appName);
        IPage<IpApplyListVo> managerIpOrderList = ipUpdateApplicationService.getManagerIpOrderList(page, appName, ip, state, userInfo.getUserId());
        return Response.success(managerIpOrderList);
    }

}
